一、pipe

概念

pipe 是nio管道2个线程之前的单项数据连接。
pipe 有2个通道一个是source通道一个是sink通道
数据会写入到source通道从sink通道获取数据。如图:
image.png

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class PipeTest {
public static void main(String[] args) {

Pipe pipe = null;
ExecutorService exec = Executors.newFixedThreadPool(2);
try {
pipe = Pipe.open();
final Pipe pipeTemp = pipe;
exec.submit(new Callable<Object>() { @Override
public Object call() throws Exception {
Pipe.SinkChannel sinkChannel = pipeTemp.sink();//向通道中写
while (true) {
TimeUnit.SECONDS.sleep(1);
String newData = "Pipe Test At Time " +
System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(1024);
buf.clear(); buf.put(newData.getBytes()); buf.flip();
while (buf.hasRemaining()) {
System.out.println(buf);
sinkChannel.write(buf);
}
}
}
});
exec.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {Pipe.SourceChannel sourceChannel = pipeTemp.source();//向
while (true) {
TimeUnit.SECONDS.sleep(1);
ByteBuffer buf = ByteBuffer.allocate(1024);
buf.clear();
int bytesRead = sourceChannel.read(buf);
System.out.println("bytesRead=" + bytesRead);
while (bytesRead > 0) {
buf.flip();
byte b[] = new byte[bytesRead]; int i = 0;
while (buf.hasRemaining()) {
b[i] = buf.get(); System.out.printf("%X", b[i]);
i++;
}
String s = new String(b);
System.out.println("=================||" + s);
bytesRead = sourceChannel.read(buf);
}

二、FileChannel文件锁

在通道中我们可以对文件或者部分文件进行上锁。上锁和我们了解的线程锁差不多,都是为 了保证数据的一致性。在文件通道 FileChannel 中可以对文件进行上锁,通过 FileLock 可以 对文件进行锁的释放。 文件加锁是建立在文件通道(FileChannel)之上的,套接字通道(SockeChannel)不考虑文 件加锁,因为它是不共享的。
它对文件加锁有两种方式:

  1. lock
  2. tryLock

两种加锁方式默认都是对整个文件加锁,如果自己配置的话就可以控制加锁的文件范围: position 是加锁的开始位置,size 是加锁长度,shared 是用于控制该锁是共享的还是独占的。

  • lock 是阻塞式的,当有进程对锁进行读取时会等待锁的释放,在此期间它会一直等待;
  • tryLock 是非阻塞式的,它尝试获得锁,如果这个锁不能获得,那么它会立即返回。

release 可以释放锁。
在一个进程中在锁没有释放之前是无法再次获得锁的
在 java 的 NIO 中,通道包下面有一个 FileLock 类,它主要是对文件锁工具的一个描述。在 上一小节中对文件的锁获取其实是 FileChannel 获取的(lock 与 trylock 是 FileChannel 的方 法),它们返回一个 FileLock 对象。

这个类的核心方法有如下这些:
boolean isShared() :判断锁是否为共享类型
abstract boolean isValid() :判断锁是否有效
boolean overlaps():判断此锁定是否与给定的锁定区域重叠 long position():返回文件内锁定区域中第一个字节的位置。
abstract void release() :释放锁
long size() :返回锁定区域的大小,以字节为单位

在文件锁中有 3 种方式可以释放文件锁:

  1. 锁类释放锁,调用 FileLock 的 release 方法
  2. 通道类关闭通道,调用 FileChannel 的 close 方法
  3. jvm 虚拟机会在特定情况释放锁。

锁类型(独占式和共享式)

我们先区分一下在文件锁中两种锁的区别:

  1. 独占式的锁就想我们上面测试的那样,只要有一个进程获取了独占锁,那么别的进程只能等待。
  2. 共享锁在一个进程获取的情况下,别的 进程还是可以读取被锁定的文件,但是别的进程不能写只能读。